package com.jsbb.util;

import org.springframework.util.Assert;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期工具类
 *
 * @author jsbb
 */
public class DateUtils {

    public static final String YM = "yyyyMM";

    public static final String YM_ = "yyyy-MM";

    public static final String YMD = "yyyyMMdd";

    public static final String YMD_ = "yyyy-MM-dd";

    public static final String YMD_HMS = "yyyy-MM-dd HH:mm:ss";

    public static final String YMDHMS = "yyyyMMddHHmmss";

    public static final String YMDHMSS = "yyyyMMddHHmmssSSS";

    public static final String[] constellationArray = {"水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "魔羯座"};

    public static final int[] constellationEdgeDay = {20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22};

    public static final String[] WEEK_NAME = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    /**
     * 一天的毫秒数
     */
    public static final int ONE_DATE_MILLISECOND = 24 * 60 * 60 * 1000;

    /**
     * @return 当前年月日时分秒
     */
    public static String getCurrentDateTime() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.format(DateTimeFormatter.ofPattern(YMD_HMS));
    }

    /**
     * @return 当前年月日
     */
    public static String getCurrentDate() {
        return LocalDate.now().toString();
    }

    /**
     * @param format
     * @return 当前年月日
     */
    public static String getCurrentDate(String format) {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * @return 当前时分秒
     */
    public static String getCurrentTime() {
        return LocalTime.now().toString();
    }

    /**
     * @return 当前年
     */
    public static int getYear() {
        return LocalDate.now().getYear();
    }

    /**
     * @return 当前月
     */
    public static int getMonth() {
        return LocalDate.now().getMonthValue();
    }

    /**
     * @return 当前日
     */
    public static int getDay() {
        return LocalDate.now().getDayOfMonth();
    }

    /**
     * @return 当前时间戳
     */
    public static long getTimeStamp() {
        return Instant.now().toEpochMilli();
    }

    /**
     * @return 当前星期几
     */
    public static String getDayOfWeek() {
        int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
        return WEEK_NAME[dayOfWeek];
    }

    /**
     * Date转字符串
     *
     * @param date   日期
     * @param format 日期格式
     * @return 字符串
     */
    public static String format(Date date, String format) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * 字符串转Date
     *
     * @param date   日期
     * @param format 日期格式
     * @return Date
     */
    public static Date parseDate(String date, String format) {
        LocalDateTime localDateTime = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(format));
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    public static Date parseDate(LocalDateTime date) {
        return Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 字符串转LocalDate
     *
     * @param date 字符串
     * @return LocalDate
     */
    public static LocalDate parseLocalDate(String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YMD_);
        return LocalDate.parse(date, formatter);
    }

    /**
     * 字符串转LocalDateTime
     *
     * @param date 字符串
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(String date) {
        return parseLocalDateTime(date, YMD_HMS);
    }

    /**
     * 字符串转LocalDateTime
     *
     * @param date   字符串
     * @param format 日期格式
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(String date, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(date, formatter);
    }

    /**
     * 字符串转long
     *
     * @param date 字符串
     * @return 时间戳
     */
    public static long string2long(String date) {
        return string2long(date, YMD_HMS);
    }

    /**
     * 字符串转long
     *
     * @param time   字符串
     * @param format 日期格式
     * @return 时间戳
     */
    public static long string2long(String time, String format) {
        Assert.notNull(time, "time is null");
        Instant instant;
        if (time.length() == 10) {
            LocalDate localDate = LocalDate.parse(time, DateTimeFormatter.ofPattern(format));
            instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        } else {
            LocalDateTime localDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
            instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        }
        return instant.toEpochMilli();
    }

    /**
     * long转字符串
     *
     * @param time   时间戳
     * @param format 日期格式
     * @return 字符串
     */
    public static String long2String(long time, String format) {
        try {
            SimpleDateFormat sf = new SimpleDateFormat(format);
            Date date = new Date(time);
            return sf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 两日期相差X天
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return int
     */
    public static int getDayDiff(Date start, Date end) {
        return (int) ((end.getTime() - start.getTime()) / ONE_DATE_MILLISECOND);
    }

    /**
     * 指定日期加X天
     *
     * @param date 指定日期
     * @param days 加X天
     * @return Date
     */
    public static Date addDay(Date date, int days) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        localDateTime.plusDays(days);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 指定日期加X月
     *
     * @param date   指定日期
     * @param months 加X月
     * @return Date
     */
    public static Date addMonth(Date date, int months) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.MONTH, months);
        return calendar.getTime();
    }

    /**
     * 指定日期加X年
     *
     * @param date 指定日期
     * @param year 加X年
     * @return Date
     */
    public static Date addYear(Date date, int year) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }

    /**
     * 指定日期加X毫秒数
     *
     * @param date        指定日期
     * @param millisecond 加X毫秒数
     * @return 字符串
     */
    public static String addTime(Date date, long millisecond) {
        SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = "";
        try {
            //1分钟60秒，1秒1000毫秒
            str = sim.format(date.getTime() + millisecond);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 当天开始时间
     *
     * @param date
     * @return
     */
    public static Date dayStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.set(Calendar.HOUR_OF_DAY, 00);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        return calendar.getTime();
    }

    /**
     * 当天结束时间
     *
     * @param date
     * @return
     */
    public static Date dayEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 本周所有日期
     *
     * @return
     */
    public static List<String> getWeekList() {
        List<String> list = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        if (c.getFirstDayOfWeek() == Calendar.SUNDAY) {
            c.add(Calendar.DAY_OF_MONTH, 1);
        }
        c.add(Calendar.DAY_OF_MONTH, -dayOfWeek);
        for (int i = 1; i <= 7; i++) {
            c.add(Calendar.DAY_OF_MONTH, 1);
            list.add(sdf.format(c.getTime()));
        }
        return list;
    }

    /**
     * 本月最后一天
     *
     * @return
     */
    public static Date getLastDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        calendar.set(Calendar.DATE, 1);
        calendar.add(Calendar.DATE, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 日期转星座
     *
     * @param date
     * @return
     */
    public static String date2Constellation(Date date) {
        if (date != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            int month = calendar.get(Calendar.MONTH);
            int day = calendar.get(Calendar.DAY_OF_MONTH);
            if (day < constellationEdgeDay[month]) {
                month = month - 1;
            }
            if (month >= 0) {
                return constellationArray[month];
            }
            return constellationArray[11];
        }
        return null;
    }
}
